#include "database.h"
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <errno.h>

int db_initialize(const char *db_path, sqlite3 **db) {
    int rc = sqlite3_open(db_path, db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(*db));
        return rc;
    }

    // 启用WAL模式以提高并发性能
    char *err_msg = NULL;
    rc = sqlite3_exec(*db, "PRAGMA journal_mode=WAL;", NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法启用WAL模式: %s\n", err_msg);
        sqlite3_free(err_msg);
    }

    // 设置同步模式为NORMAL以提升性能
    rc = sqlite3_exec(*db, "PRAGMA synchronous=NORMAL;", NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法设置同步模式: %s\n", err_msg);
        sqlite3_free(err_msg);
    }

    const char *sql = "CREATE TABLE IF NOT EXISTS files ("
                      "fileName TEXT PRIMARY KEY NOT NULL,"
                      "fileSize INTEGER NOT NULL,"
                      "fileHash TEXT NOT NULL);";

    rc = sqlite3_exec(*db, sql, NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(*db);
        return rc;
    }

    // 创建索引以加速重复文件查询
    const char *index_sql = "CREATE INDEX IF NOT EXISTS idx_fileHash ON files(fileHash);";
    rc = sqlite3_exec(*db, index_sql, NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法创建索引: %s\n", err_msg);
        sqlite3_free(err_msg);
    }

    return SQLITE_OK;
}

int db_file_exists(sqlite3 *db, const char *file_path) {
    const char *sql = "SELECT 1 FROM files WHERE fileName = ?";
    sqlite3_stmt *stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        return 0;
    }

    sqlite3_bind_text(stmt, 1, file_path, -1, SQLITE_STATIC);

    int exists = 0;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        exists = 1;
    }

    sqlite3_finalize(stmt);
    return exists;
}

int db_insert_or_update_file(sqlite3 *db, const FileInfo *file_info) {
    const char *sql = "INSERT OR REPLACE INTO files (fileName, fileSize, fileHash) "
                      "VALUES (?, ?, ?)";
    sqlite3_stmt *stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法准备SQL语句: %s\n", sqlite3_errmsg(db));
        return rc;
    }

    sqlite3_bind_text(stmt, 1, file_info->file_name, -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 2, file_info->file_size);
    sqlite3_bind_text(stmt, 3, file_info->file_hash, -1, SQLITE_STATIC);

    rc = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (rc != SQLITE_DONE) {
        fprintf(stderr, "数据库插入失败: %s\n", sqlite3_errmsg(db));
        return rc;
    }

    return SQLITE_OK;
}


int db_delete_nonexistent_files(sqlite3 *db) {
    const char *sql = "SELECT fileName FROM files";
    sqlite3_stmt *stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        return rc;
    }

    int deleted_count = 0;
    printf("开始清理数据库中不存在的文件记录...\n");

    while (sqlite3_step(stmt) == SQLITE_ROW) {
        const char *file_path = (const char *)sqlite3_column_text(stmt, 0);

        struct stat st;
        if (stat(file_path, &st) != 0) {
            const char *delete_sql = "DELETE FROM files WHERE fileName = ?";
            sqlite3_stmt *delete_stmt;

            if (sqlite3_prepare_v2(db, delete_sql, -1, &delete_stmt, NULL) == SQLITE_OK) {
                sqlite3_bind_text(delete_stmt, 1, file_path, -1, SQLITE_STATIC);
                if (sqlite3_step(delete_stmt) == SQLITE_DONE) {
                    printf("删除: %s\n", file_path);
                    deleted_count++;
                }
                sqlite3_finalize(delete_stmt);
            }
        }
    }

    sqlite3_finalize(stmt);

    if (deleted_count == 0) {
        printf("没有找到需要清理的文件记录。\n");
    } else {
        printf("清理完成。共删除了 %d 个不存在的文件记录。\n", deleted_count);
    }

    return SQLITE_OK;
}

int db_find_duplicate_files(sqlite3 *db) {
    const char *sql = "SELECT fileHash, fileSize, fileName "
                      "FROM files "
                      "WHERE fileHash IN ("
                      "    SELECT fileHash "
                      "    FROM files "
                      "    GROUP BY fileHash "
                      "    HAVING COUNT(*) > 1"
                      ") "
                      "ORDER BY fileSize DESC;";

    sqlite3_stmt *stmt;
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db));
        return rc;
    }

    printf("Duplicate files (sorted by size):\n");
    printf("fileHash | fileSize | fileName\n");
    printf("----------------------------------------\n");

    int count = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        const char *fileHash = (const char *)sqlite3_column_text(stmt, 0);
        int64_t fileSize = sqlite3_column_int64(stmt, 1);
        const char *fileName = (const char *)sqlite3_column_text(stmt, 2);

        printf("%s | %" PRId64 " | %s\n", fileHash, fileSize, fileName);
        count++;
    }

    sqlite3_finalize(stmt);

    if (count == 0) {
        printf("No duplicate files found.\n");
    } else {
        printf("Found %d duplicate file entries.\n", count);
    }

    return SQLITE_OK;
}
